工作学习过程中,我们可能需要去阅读不同类型的 Native 系统服务,也有可能会自己去完成一个 Native 系统服务。无论哪种情况都需要我们了解基本的 Native 如何去添加。就像我们写 Android App 得先了解一下四大组件才行。接着我们就来看看如何添加一个 Android Native 系统服务。使用的源码版本是 AOSP android_r41。
文章配套源码:https://github.com/yuandaimaahao/HelloNativeService
接下来,我们就来添加我们的 Native 系统服务
在 device/jelly/rice14/HelloNativeService
目录下创建包目录 com/yuandaima
接着在包目录下创建:
package com.yuandaima;
interface IHello {
void hello();
int sum(int x, int y);
}
2
3
4
5
6
接着在项目目录下执行下面的命令,生产源文件:
aidl-cpp com/yuandaima/IHello.aidl ./ ./IHello.cpp
接着我们完善 HelloServer 程序
#define LOG_TAG "helloserver"
#include <log/log.h>
#include <unistd.h>
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "com/yuandaima/IHello.h"
#include "com/yuandaima/BnHello.h"
using namespace android;
class MyHelloService : public com::yuandaima::BnHello
{
public:
binder::Status hello()
{
ALOGI("server hello function is running");
return binder::Status();
}
binder::Status sum(int32_t x, int32_t y, int32_t* _aidl_return)
{
ALOGI("server sum function is running");
*_aidl_return = x + y;
return binder::Status();
}
};
int main(int argc, char const *argv[])
{
ALOGD("Hello Server is runing");
defaultServiceManager()->addService(String16("MyHelloService"), new MyHelloService());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
接着我们写一个 HelloClient 来测试我们的服务程序:
#define LOG_TAG "aidl_cpp"
#include <log/log.h>
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "com/yuandaima/IHello.h"
#include "com/yuandaima/BpHello.h"
using namespace android;
int main(int argc, char const *argv[])
{
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("MyHelloService"));
sp<com::yuandaima::IHello> hello = interface_cast<com::yuandaima::IHello>(binder);
hello->hello();
int ret = 0;
hello->sum(1, 2, &ret);
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
然后,完善 Android.bp
cc_binary {
name: "HelloServer",
srcs: ["HelloServer.cpp", "IHello.cpp"],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libbinder",
],
init_rc: ["HelloServer.rc"],
}
cc_binary {
name: "HelloClient",
srcs: ["HelloClient.cpp", "IHello.cpp"],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libbinder",
],
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Selinux 配置
我们的 Native 程序是添加在 System 分区的,不能在自定义 Product 的 sepolicy 中添加 selinux 配置,需要修改系统的 sepolicy 配置文件:
在 system/sepolicy/private
和system/sepolicy/prebuilts/api/29.0/private
中同时添加:
helloserver.te:
type helloserver_dt, domain, coredomain;
type helloserver_dt_exec, exec_type, file_type, system_file_type;
init_daemon_domain(helloserver_dt)
allow helloserver_dt servicemanager:binder { call transfer };
allow helloserver_dt HelloServer_service:service_manager { add find };
# binder_use(helloserver_dt)
# add_service(helloserver_dt,HelloServer_service)
2
3
4
5
6
7
8
9
10
编译时,编译系统会同时检查这两个目录,如果不同就会报错,所以我们要同时修改两个地方。
在 system/sepolicy/private/file_contexts
和 system/sepolicy/prebuilts/api/29.0/private/file_contexts
中添加:
/system/bin/HelloServer u:object_r:helloserver_dt_exec:s0
2
注意 file_contexts 最后一行必须是空行,不然无法编译过。
在 system/sepolicy/private/service_contexts
和 system/sepolicy/prebuilts/api/29.0/private/service_contexts
中倒数第二行添加
MyHelloService u:object_r:HelloServer_service:s0
2
注意 service_contexts 最后一行必须是空行,不然无法编译过。
在 system/sepolicy/private/service.te
和 system/sepolicy/prebuilts/api/29.0/private/service.te
最后一行中添加:
type HelloServer_service, service_manager_type;
最后编译启动模拟器:
source build/envsetup.sh
lunch rice14-eng
make -j32
emulator
# 进入 Android 模拟器
adb shell
logcat | grep hello
2
3
4
5
6
7
然后就可以看到 Log 了:
07-16 16:42:11.616 1534 1534 D helloserver: Hello Server is runing
接着我们运行我们的客户端程序,再查看 Log:
logcat | grep "hello"
07-16 16:57:46.794 1531 1531 D helloserver: Hello Server is runing
07-16 16:58:52.638 1531 1577 I helloserver: server hello function is running
07-16 16:58:52.638 1531 1577 I helloserver: server sum function is running
2
3
4
这样,我们的远程调用就成功了。
最后给同学们留一个问题,HelloClient 为什么没有配 Selinux 权限也能执行,如果要配置,应该怎么配置?(这部分内容我们会留在 SeAndroid 部分来解答)